#include "../../include/logs/Logs.h"


namespace Circle {
    namespace Logs {
        std::unordered_map<std::string, std::shared_ptr<spdlog::logger>> logMap;
        std::unordered_map<std::string, std::chrono::time_point<std::chrono::steady_clock>> lastUsedTimeMap;
        std::string logPattern = "%Y-%m-%d %H:%M:%S.%e [%l] %v";
        spdlog::level::level_enum logLevel = spdlog::level::info;
        std::string defaultFilename =  "circle_app.log";
        std::shared_ptr<spdlog::logger> logger;
        std::mutex logMapMutex;
        const std::chrono::minutes timeoutDuration(30); // 预设超时时间，30 分钟
        const size_t maxFileSize = 1024 * 1024; // 每个日志文件的最大大小，这里设置为 1MB
        const size_t maxFiles = 5; // 最多保留的日志文件数量

        // 获取当前日期和时间戳，格式为年-月-日_时间戳
        std::string getDateTimeStamp() {
            auto now = std::chrono::system_clock::now();
            auto now_c = std::chrono::system_clock::to_time_t(now);
            auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;

            std::ostringstream oss;
            oss << std::put_time(std::localtime(&now_c), "%Y-%m-%d") << '_'
                << std::put_time(std::localtime(&now_c), "%H%M%S") << '.' << std::setfill('0') << std::setw(3) << now_ms.count();
            return oss.str();
        }

        std::shared_ptr<spdlog::logger> init(){
            return init(defaultFilename);
        }

        std::shared_ptr<spdlog::logger> init(const std::string& logFilename) {
            std::lock_guard<std::mutex> lock(logMapMutex);

            // 检查并销毁长时间未使用的实例
            auto now = std::chrono::steady_clock::now();-
            for (auto it = lastUsedTimeMap.begin(); it != lastUsedTimeMap.end(); ) {
                if (now - it->second > timeoutDuration) {
                    std::string filename = it->first;
                    // 从 logMap 中移除
                    logMap.erase(filename);
                    // 从 lastUsedTimeMap 中移除
                    it = lastUsedTimeMap.erase(it);
                } else {
                    ++it;
                }
            }

            std::filesystem::path logDirectory = std::filesystem::path(Circle::Paths::__LOG__);
            // 查找是否已经存在对应 filename 的日志记录器实例
            auto it = logMap.find(logFilename);
            if (it != logMap.end()) {
                // 如果存在，更新最后使用时间并返回旧实例
                lastUsedTimeMap[logFilename] = std::chrono::steady_clock::now();
                return it->second;
            }

            // 生成日期 + 时间戳 + 文件名的格式
            std::string dateTimeStamp = getDateTimeStamp();
            std::string newLogFilename = dateTimeStamp + "_" + logFilename;
            std::filesystem::path logFilePath = logDirectory / std::filesystem::path(newLogFilename);

            // 若不存在，则创建新的日志记录器实例
            try {
                auto fileSink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logFilePath.string(), maxFileSize, maxFiles);
                auto newLogger = std::make_shared<spdlog::logger>("circle_logger_" + newLogFilename, fileSink);
                newLogger->set_pattern(logPattern);
                newLogger->set_level(logLevel);

                // 将新创建的日志记录器实例存入 map 中
                logMap[newLogFilename] = newLogger;
                lastUsedTimeMap[newLogFilename] = std::chrono::steady_clock::now();
                return newLogger;
            } catch (const spdlog::spdlog_ex& ex) {
                // 处理 spdlog 异常
                std::cerr << "Failed to create logger for " << newLogFilename << ": " << ex.what() << std::endl;
                return nullptr;
            }
        }

        void setLogPattern(const std::string& pattern) {
            std::lock_guard<std::mutex> lock(logMapMutex);
            logPattern = pattern;
            if (logger) {
                logger->set_pattern(logPattern);
                lastUsedTimeMap[logger->name()] = std::chrono::steady_clock::now();
            } else {
                init();
                logger->set_pattern(logPattern);
                lastUsedTimeMap[logger->name()] = std::chrono::steady_clock::now();
            }
        }

        void setLogLevel(spdlog::level::level_enum level) {
            std::lock_guard<std::mutex> lock(logMapMutex);
            logLevel = level;
            if (logger) {
                logger->set_level(level);
                lastUsedTimeMap[logger->name()] = std::chrono::steady_clock::now();
            } else {
                init();
                logger->set_level(level);
                lastUsedTimeMap[logger->name()] = std::chrono::steady_clock::now();
            }
        }

        void setLogFilename(const std::string& filename) {
            std::lock_guard<std::mutex> lock(logMapMutex);
            const std::string logFilename = filename;

            if (logger) {
                spdlog::drop("circle_logger");
                logger.reset();
            }
            init(filename);
        }
    }
}